Feature/browserlend2#1
Merged
Merged
Conversation
added 30 commits
May 5, 2026 06:53
…onnect backoff (#128)
- Browser: CDP roundtrip with pending futures, error code mapping (-1011/-1012/-1013/-1015/-1018/-1050), session lifecycle, on_event/on_tab_opened callbacks, switch_tab, configure, close - BrowserChat: send/send_image with ack, on_message/on_read callbacks, REST history endpoint; mime autodetect (PNG/JPEG/WEBP magic bytes), 5MB size limit - Client._dispatch: chat routing (chat.message/read/send_ack), per-session error routing - Tests: 25 new tests covering CDP happy path, error codes, multi-session routing, tab_opened, chat send/ack, image mime detection, history - Examples: navigate.py, captcha_helper.py
- reddit_signup.py: full Reddit signup flow via CDP — navigate, form fill, captcha screenshot→chat→answer, IMAP confirm-link parse - github_signup.py: GitHub signup with multi-round captcha loop - imap_helper.py: wait_for_confirm_link with IMAP4_SSL poll + regex for Reddit and GitHub confirm URLs, plus-addressing support - examples/SMOKE.md: runbook with pre-requisites, env vars, checklists - test_examples_signature.py: import + signature checks via inspect - README.md: Real-signup examples section with disclaimer
relay.ittribe.org / relay.ceki.me never existed — relay runs at browser.<domain>/ws/agent. Mirrors the same fix done for extension config.ts in plugin/142.
…/duration_minutes (v2.1.0)
…tion nullable BREAKING: connect(api_key, ConnectOptions(...)) replaces kwargs. - _connect.py: ConnectOptions dataclass (api_url, relay_url, basic_auth, reconnect) - _config.py: prod-only defaults + CEKI_API_URL/CEKI_RELAY_URL env override - _client.py: api_url + basic_auth fields; search() uses /api/browsers/search (plural); basic_auth forwarded as httpx.BasicAuth + WS extra_headers for relay upgrade - _models.py: BrowserOption geo/language nullable, language singular added, extra='ignore' - __init__.py: exports ConnectOptions, version 2.2.0
httpx.BasicAuth passed as auth= to AsyncClient would overwrite the explicit Authorization: Bearer header, causing 401 on dev/staging where nginx basic-auth sits in front of Laravel API.
…helpers + provider_user_id - ChatMessage: _id alias, sender_id, text, media, type, created_at (drop message_id/sender_type/sent_at) - ChatMessage.is_system(): returns type == 'system' - ChatMessage.is_from_provider(uid): returns sender_id == uid - Match.provider_user_id: parsed from relay match payload - Browser.provider_user_id: property from match - examples: replace msg.sender_type == 'provider' with is_system()/is_from_provider() - tests: update fixtures (chat_topic_id as str), new unit tests for all helpers
…fast, handshake 429+4403 (BUG-3..6) - _config.py: DEFAULT_CHAT_URL, default_chat_url() for separate chat host - _connect.py: ConnectOptions.chat_url passed through to Client - _client.py: Client.chat_url attr; 429 → RateLimitExceeded; WS 4401/4403 → AuthFailed; rent.error → ProviderOffline; chat.error → ChatSendFailed - _chat.py: history() uses client.chat_url, before param (not before_id); send_image payload: filename+data_b64 (was base64); _on_send_error() - _exceptions.py: ChatSendFailed, ProviderOffline - tests/test_chat_history.py: new tests for history URL/params
…allbacks - ProviderDisconnected(CekiError) raised when session ends with reason provider_disconnected - Browser.on_provider_disconnected(cb) / on_provider_reconnected(cb) callbacks - Dispatch session.provider_disconnected and session.provider_reconnected relay events - Export ProviderDisconnected from package __init__
…restore BrowserProfile wraps CDP calls to export cookies (with optional domain filter), localStorage, and sessionStorage into a plain dict. import_() restores them into a new session before/after first navigation. Profile data stays agent-side — relay and backend never see it.
Handles rent.error with event_id (post-rent_pending) by resolving via _pending_rents. Adds test_provider_offline.py with 2 pytest cases.
…5, reason↔message fallback _connect() probes with 1s recv after websockets.connect() to catch post-handshake 4401/4403 close before any rent is pending. _handle_error maps -1015 to ProviderOffline. reason or message fallback everywhere so relay errors don't stringify as "None".
Replace broken mvp_smoke_p2p.py with new mvp_smoke_v2.py in examples/smoke/. Scenarios A-K using current public API: connect(), client.rent(), browser.send() with raw CDP commands. Window init via Page.navigate about:blank before Page.enable. Scenario A verified PASS against schedule 240.
…E_ID
- github_signup.py / reddit_signup.py: drop required SCHEDULE_ID env, default
to client.search({})[0].schedule_id; SCHEDULE_ID kept as optional pin.
Empty result → graceful exit (no blocking on a single offline provider).
- imap_helper.py + github_signup.py: thread EMAIL_BASE env through plus-tag
IMAP search so non-kom@ceki.me addresses work.
Add navigate(), click(), type(), scroll(), screenshot(), set_human() to Browser class. Humanizer wraps actions with pre/post delays and per-char typing with jitter. Supports profiles: natural (default), careful, custom dict/file, or None to disable. Client.rent() accepts human= kwarg. Env vars: CEKI_HUMAN_PROFILE, CEKI_HUMAN_PROFILE_PATH, CEKI_HUMAN_DISABLE. SDK version bumped to 2.3.0. 14 new tests, 89 total passing.
…mode=False v0.6.83
…ng bytes (v2.3.2)
- Add _last_pointer tracking to Browser (set by click/scroll) - type() calls click() at last known pointer before insertText when humanizer is on - Debug log when no pointer available, graceful fallback to plain insertText - 4 test cases covering all humanizer × pointer combinations - Bump version 2.3.2 → 2.3.3
- CLI entry point `ceki-browser` with 9 subcommands: rent, snapshot, navigate, click, type, scroll, chat send/next, stop - Client.resume(session_id) reconnects to existing session via relay - Browser.snapshot() captures screenshot + new chat messages - State files in ~/.ceki/sessions/ for cross-process persistence - New exceptions: SessionNotFound, SessionExpired, NotOwner - Snapshot model, since param for chat.history - README: CLI section with 3 examples, subcommand table, exit codes - Version 2.3.3 → 2.4.0
Root cause: chat.history(since=ts) passes 'since' as HTTP param but chat-service may not implement server-side filtering. Second snapshot in a new process loads last_seen_ts from state file correctly, but gets the same messages back from the server. Fix: add client-side filtering in Browser.snapshot() — messages with created_at <= last_seen_ts are excluded regardless of server behavior. Also persist last_seen_ts from browser object rather than snap.chat to handle edge cases. Version 2.4.0 → 2.4.1
profile export/import, search, chat history, chat send-image, wait, screenshot, switch-tab, configure, cdp. All 138 tests pass. Version bumped to 2.5.0.
New Browser.upload() method and CLI `ceki-browser upload` subcommand. Injects file via base64 + DataTransfer + change event into any input[type=file]. MIME detection by extension, supports path and bytes. Bump to v2.6.0.
…print=...) - profile.export() includes Browser.getFingerprint response - profile.import_() backward-compat v1 (no fingerprint) - client.rent(fingerprint=dict|False|True) sends session.configure - CLI: rent --fingerprint-from PROFILE.json - v2.6.0 -> v2.7.0 Задача: 253-profile-fingerprint-persist.md от main
added 22 commits
May 13, 2026 08:09
- tests/e2e/test_fingerprint_persistence.py — real rent against browser.ittribe.org - tests/e2e/README.md — setup and run instructions - skipped by default (requires CEKI_API_KEY env var) Задача: 254-profile-fingerprint-commit-release-e2e.md от main
… 0.6.102) - profile.export() catches exception, sets fingerprint=None - E2E test skips gracefully when extension too old - new unit test: export_fingerprint_fallback_on_old_extension Задача: 254-profile-fingerprint-commit-release-e2e.md от main
- browser.screenshot(full_page=True) uses Page.getLayoutMetrics + captureBeyondViewport - CLI: ceki-browser screenshot <sid> -o file.png --full - Safety clamp at 16384px height with warning - Default behavior unchanged (viewport-only) - v2.7.0 → v2.7.1 Задача: 255-screenshot-full-page.md от main
Emit real keyDown/keyUp CDP events per character instead of insertText, so reCAPTCHA/hCaptcha see genuine keyboard event timing and sequence. - Add humanize/keymap.py with US keyboard layout mapping - Add _send_keystroke() helper: keyDown+keyUp with Shift wrapping - Non-ASCII chars fall back to Input.insertText - Bump version to 2.8.0
Backend requires browser_id in POST /api/sessions. CLI --schedule param preserved for UX, mapped to browser_id internally.
Closes WS without sending session.end for active browsers.
Prevents reconnect-loop spawn on CLI subprocess exit. All 16 subcommands now use the public disconnect() API which properly sets _closed flag and cancels background tasks.
After #289 the SDK sends browser_id in the rent WS message, but test assertions still expected schedule_id. Added disconnect-not-close guard test. Bump 2.8.1.
…ption Bump 2.10.0
CLI: --mode incognito|main. SDK: rent(schedule_id, mode='main'). Default incognito. v2.12.0
When relay sends match with requires_ack=true, SDK immediately responds with match_ack to confirm session readiness before billing starts.
- Browser.request_captcha(acceptance_timeout, completion_timeout, auto_accept) - CaptchaResult with accept_work/reject_work for double-acceptance model - CaptchaError + CaptchaTimeoutError exception classes - CLI: ceki-browser request-captcha <sid> [--acceptance N] [--completion M] - Action queue in BrowserChat for intercepting action messages - Hard min 30s on both timeouts, max 300/600 - 4 tests: happy path, acceptance timeout, provider declined, min timeout - Version bump 2.12.0 → 2.13.0
- accept_work/reject_work vote via /api/agent/kal/event/{id}/vote
- event store/expire via /api/agent/kal/event/* endpoints
- correction_id is now public on CaptchaResult
- raise CaptchaError when correction_id missing (was silent no-op)
- CLI: --manual flag, correction_id in output
- bump v2.14.0
acceptance_deadline_at / completion_deadline_at now sent as integer seconds instead of ISO datetime strings. Contract aligned with backend (ceki-back/168).
…nt}/captcha-request Minimal payload with acceptance_deadline_at and completion_deadline_at only. Backend resolves price from schedule settings.
GET /api/agent/sessions?active=1&limit=50. Table output by default, --json for raw. --all shows non-active too.
… orphaned asyncio warnings
Mirror CLI documentation from browser.ceki.me/docs — install, env vars, quick start with search→rent chain, 4 command groups, exit codes.
Remove dev/staging code block containing *.ittribe.org URLs and basic-auth credentials. Production URLs are already documented in ConnectOptions defaults table.
iWedmak
added a commit
that referenced
this pull request
May 27, 2026
Merge pull request #1 from Ceki-me/feature/browserlend2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.